/*
 * application.cpp
 *
 *  Created on: 2009-1-6
 *      Author: fanliangliang
 */

#include "application.h"
#include "connection_listener.h"
#include "file_receiver.h"
#include "file_sender.h"
#include "file_deleter.h"
#include "uncompressor.h"
#include "protocol.h"

using namespace toxic;

Application::Application()
:listener_(0)
,receiver_(0)
,sender_(0)
,uncompressor_(0)
,isRunning_(false) {

}

Application::~Application() {
	stop();
}

static void deleteHandler(const string& filename) {
	FileDeleter::instance()->releaseFile(filename, 1);
}

void Application::start() {
	if (!isRunning_) {
		startLog();
		startWorkerThread();
		isRunning_ = true;
	}
}

void Application::stop() {
	if (isRunning_) {
		stopWorkerThread();
		stopLog();
		isRunning_ = false;
	}
}

int16_t Application::status() const {
	int16_t status = 0;
	if (receiver_->isProcessing()) {
		status |= DU::STATUS_RECEIVING;
	}

	if (sender_->isProcessing()) {
		status |= DU::STATUS_SENDING;
	}

	if (uncompressor_->isProcessing()) {
		status |= DU::STATUS_UNCOMPRESSING;
	}

	if (status == 0) {
		status = DU::STATUS_ALL_IDLE;
	}
	return status;
}

void Application::startLog() {
	xlog.setLevel(Log::TRACE);
	xlog.addAppender("log/%y-%m-%d.log");
}

void Application::stopLog() {
	// it is better to shutdown manually
	xlog.shutdown();
}

void Application::startWorkerThread() {
	uncompressor_ = new Uncompressor();
	sender_ = new FileSender();
	sender_->setFileDeleteHandler(&deleteHandler);
	receiver_ = new FileReceiver(sender_, uncompressor_);
	listener_ = new ConnectionListener(receiver_, this);

	uncompressor_->start();
	sender_->start();
	receiver_->start();
	listener_->start();
}

void Application::stopWorkerThread() {
	// stop in reverse order
	listener_->stop();
	listener_->join();

	receiver_->stop();
	receiver_->join();

	sender_->stop();
	sender_->join();

	uncompressor_->stop();
	uncompressor_->join();

	delete listener_;
	delete receiver_;
	delete sender_;
	delete uncompressor_;
}
